package com.tataben.db.converter;

import com.tataben.db.DLLogger;

import java.sql.Date;
import java.util.concurrent.ConcurrentHashMap;

public final class DLCCFactory {

    private DLCCFactory() {}

    public static ColumnConverter getColumnConverter(Class columnType) {
        ColumnConverter result = null;
        if (columnType_columnConverter_map.containsKey(columnType.getName())) {
            result = columnType_columnConverter_map.get(columnType.getName());
        } else if (ColumnConverter.class.isAssignableFrom(columnType)) {
            try {
                ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
                if (columnConverter != null) {
                    columnType_columnConverter_map.put(columnType.getName(), columnConverter);
                }
                result = columnConverter;
            } catch (Throwable ex) {
                DLLogger.e(ex.getMessage(), ex);
            }
        }

        if (result == null) {
            throw new RuntimeException("Database Column Not Support: " + columnType.getName() + ", please impl ColumnConverter or use DLCCFactory#registerColumnConverter(...)");
        }

        return result;
    }

    public static ColumnType getDbColumnType(Class columnType) {
        ColumnConverter converter = getColumnConverter(columnType);
        return converter.getColumnDbType();
    }

    public static void registerColumnConverter(Class columnType, ColumnConverter columnConverter) {
        columnType_columnConverter_map.put(columnType.getName(), columnConverter);
    }

    public static boolean isSupportColumnConverter(Class columnType) {
        if (columnType_columnConverter_map.containsKey(columnType.getName())) {
            return true;
        } else if (ColumnConverter.class.isAssignableFrom(columnType)) {
            try {
                ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
                if (columnConverter != null) {
                    columnType_columnConverter_map.put(columnType.getName(), columnConverter);
                }
                return columnConverter == null;
            } catch (Throwable e) {
            }
        }
        return false;
    }

    private static final ConcurrentHashMap<String, ColumnConverter> columnType_columnConverter_map;

    static {
        columnType_columnConverter_map = new ConcurrentHashMap<>();

        DLBoolCC booleanColumnConverter = new DLBoolCC();
        columnType_columnConverter_map.put(boolean.class.getName(), booleanColumnConverter);
        columnType_columnConverter_map.put(Boolean.class.getName(), booleanColumnConverter);

        DLBytesCC byteArrayColumnConverter = new DLBytesCC();
        columnType_columnConverter_map.put(byte[].class.getName(), byteArrayColumnConverter);

        DLByteCC byteColumnConverter = new DLByteCC();
        columnType_columnConverter_map.put(byte.class.getName(), byteColumnConverter);
        columnType_columnConverter_map.put(Byte.class.getName(), byteColumnConverter);

        DLCharCC charColumnConverter = new DLCharCC();
        columnType_columnConverter_map.put(char.class.getName(), charColumnConverter);
        columnType_columnConverter_map.put(Character.class.getName(), charColumnConverter);

        DLDateCC dateColumnConverter = new DLDateCC();
        columnType_columnConverter_map.put(Date.class.getName(), dateColumnConverter);

        DLDoubleCC doubleColumnConverter = new DLDoubleCC();
        columnType_columnConverter_map.put(double.class.getName(), doubleColumnConverter);
        columnType_columnConverter_map.put(Double.class.getName(), doubleColumnConverter);

        DLFloatCC floatColumnConverter = new DLFloatCC();
        columnType_columnConverter_map.put(float.class.getName(), floatColumnConverter);
        columnType_columnConverter_map.put(Float.class.getName(), floatColumnConverter);

        DLIntegerCC integerColumnConverter = new DLIntegerCC();
        columnType_columnConverter_map.put(int.class.getName(), integerColumnConverter);
        columnType_columnConverter_map.put(Integer.class.getName(), integerColumnConverter);

        DLLongCC longColumnConverter = new DLLongCC();
        columnType_columnConverter_map.put(long.class.getName(), longColumnConverter);
        columnType_columnConverter_map.put(Long.class.getName(), longColumnConverter);

        DLShortCC shortColumnConverter = new DLShortCC();
        columnType_columnConverter_map.put(short.class.getName(), shortColumnConverter);
        columnType_columnConverter_map.put(Short.class.getName(), shortColumnConverter);

        DLSqlDateCC sqlDateColumnConverter = new DLSqlDateCC();
        columnType_columnConverter_map.put(Date.class.getName(), sqlDateColumnConverter);

        DLStringCC stringColumnConverter = new DLStringCC();
        columnType_columnConverter_map.put(String.class.getName(), stringColumnConverter);
    }
}
